using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;
using JigLibX.Physics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SolarWinds.Helpers;

namespace SolarWinds.Shapes
{
    public class ProjectileShape : ModelShape
    {
        public Vector3 Direction { get; set; }
        private float mLifeTime;
        public float LifeTime
        {
            get { return mLifeTime; }
        }
        public bool Killed = false;

        private readonly Body mBody;
        private readonly CollisionSkin mSkin;
        private Vector3 mCenterOfMass;

        private StateBlock mStateBlock;

        public ProjectileShape(Game game)
            : base(game, "projectile01")
        {
            BoundingBoxVisible = true;
            BoundingSphereVisible = true;

            mBody = new Body();
            mBody.ExternalData = this;
            mSkin = new CollisionSkin(mBody);
            mBody.CollisionSkin = mSkin;
            mLifeTime = 3000;  // TODO move to ProjectileData
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                mBody.DisableBody();
            }
        }

        protected override void LoadContent()
        {
            base.LoadContent();

            mStateBlock = new StateBlock(Game.GraphicsDevice);

            var sphere = new Sphere(BoundingSphere.Center, BoundingSphere.Radius * Scale.X);
            mSkin.AddPrimitive(sphere, new MaterialProperties(0.8f, 0.8f, 0.7f));

            mCenterOfMass = PhysicsHelper.SetMass(10.0f, mSkin, mBody);

            mBody.SetBodyInvInertia(0.0f, 0.0f, 0.0f);
            mBody.MoveTo(Position, Matrix.CreateFromQuaternion(Rotation));
            mBody.Velocity = Direction;
            mSkin.ApplyLocalTransform(new Transform(-mCenterOfMass, Matrix.Identity));
            mBody.EnableBody();

            mSkin.callbackFn += new CollisionCallbackFn(SkinCallbackFn);
        }

        bool SkinCallbackFn(CollisionSkin owner, CollisionSkin collidee)
        {
            if (collidee.Owner.ExternalData is ProjectileShape ||
                collidee.Owner.ExternalData is ShipShape)
            {
                return false;
            }
            if (collidee.Owner.ExternalData is AsteroidShape)
            {
                // collision with asteroid
                Killed = true;
                return false;
            }

            return false;
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            var elapsedTime = (float) gameTime.ElapsedGameTime.TotalMilliseconds;
            mLifeTime -= elapsedTime;

            Position = mBody.Position;
            Rotation = Quaternion.CreateFromRotationMatrix(
              mSkin.GetPrimitiveLocal(0).Transform.Orientation *
              mBody.Orientation);
        }
        
        public override void  Draw(GameTime gameTime)
        {
 	        base.Draw(gameTime);
 
            mStateBlock.Capture();

            GraphicsDevice device = Game.GraphicsDevice;

            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.SourceBlend = Blend.SourceAlpha;
            device.RenderState.DestinationBlend = Blend.One;
            device.RenderState.CullMode = CullMode.None;
            device.RenderState.DepthBufferWriteEnable = false;

            base.Draw(gameTime);

            mStateBlock.Apply();
        }
    }
}